#ifndef _LOGIC_H_
#define _LOGIC_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include "network.h"
#include <json/value.h>
#include <json/reader.h>
#include <json/writer.h>
#include <boost/atomic.hpp>
#include "gametimer.h"
#include "mj.h"

using namespace std;

struct RobotRule
{
	int _min_sec;		//出牌最小时间
	int _max_sec;		//出牌最大时间
	int _min_gang_sec;		//杠牌最小延时
	int _min_peng_sec;		//碰牌最小延时
	int _min_hu_sec;		//胡牌最小延时
	int _max_gang_sec;		//杠牌最大延时
	int _max_peng_sec;		//碰牌最大延时
	int _max_hu_sec;		//胡牌最大延时
	map<int, int> _out_time;		//出牌时间
	map<int, int> _hu_time;		//胡牌时间
	map<int, int> _peng_time;			//碰牌时间
	map<int, int> _gang_time;			//杠牌时间
};

typedef struct
{
   int uid;
   int seatid;
}Players; 

typedef enum
{
    NOT_READY = 0,              //游戏中未准备
    READY = 1,                  //准备
    INPlAY = 2,                 //游戏中
    INPLAY_AFTER_GETIN_MJ = 3,  //刚摸完牌，还没操作(可报听，自摸胡，暗杠，明杠)
    INPLAY_AFTER_PUTOUT_MJ = 4, //刚打出一张牌，还没操作(其他玩家可碰，放杠，放炮胡)
    INPLAY_AFTER_PENG_MJ = 5,   //刚碰了一张牌，还没操作(可亮倒，暗杠)
} STATUS;


class LogicTask : public session , public AsyncTimer
{
public:
	static string url;
	void init()
	{
		proto_cnt = 0;
		board_cnt = 0;
	}
protected:
	virtual int Getuid() override 
	{
		return uid;
	}
	virtual void do_first() override
	{
		if (!socket_.is_open())
		{
			cout << uid << " is die!" << endl;
			return;
		}
		do_read();
		clear_hand();
		cout << uid << " is do first!" << endl;
		_on_seat = false;
		//join_room_req();
		//_join_room_timer.start();
	}
	virtual string handle_cmd(const char* content, size_t length) override
	{
// 		string content_str(content, length);
// 		xorfunc(content_str);
// 		Header header;
// 		header.length = content_str.size();
// 		string str;
// 		str.append((const char *)&header, sizeof(struct Header));
// 		str.append(content_str, content_str.size());
		string str(content, length);
		recv_data(str);
		proto_cnt++;
		return str;
	}
	void clear_hand() {
		_hand_mjs.clear();
		_has_que = 0;
	}
	//将协议里的手牌json转化到容器里面
	void json_turn_hand_mjs(const Json::Value& val)
	{
		if (val.isMember("mjs_info"))
		{
			auto mjs = val["mjs_info"];
			if (mjs.isMember("hole_mjs"))
			{
				auto hole_mjs = mjs["hole_mjs"];
				_hand_mjs.clear();
				for (auto& mj : hole_mjs)
				{
					_hand_mjs.push_back(Mj(mj.asInt()));
				}
			}
		}
	}
	string printHands(std::vector<Mj>& mjs)
	{
		string str_mj;
		for (auto& mj : mjs)
		{
			str_mj.append(to_string(mj.val % 10));
			str_mj.append(" ");
		}
		return str_mj;
	}
public:
    LogicTask(boost::asio::io_service& io_context_,int id, string ip, short port, RobotRule rule);
	virtual tcp::socket connect(boost::asio::io_service& io_context_, string ip = "", short port = 0) override;
    void run(void);
	static int random(int start, int end, double pow_num = 1.0);
	int getuid(int id);
	int ping();
	int join_room_req();
    int ready_req();
    int peng_req();
    int ang_gang_req(int mj);
    int ming_gang_req();
    int fang_gang_req();
    int out_mj_req();
    int auto_out_mj_req();
    int zimo_hu_req();
    int fang_pao_hu();
    int qiang_gang_hu();
    int goldroom_logout_req();
	int do_ding_que(int dq);
	int cancel_robot();

	int recv_data(string content);


    int handler_cmd_SERVER_ENTER_ROOM_UC();
    int handler_cmd_SERVER_ROOM_INFO_BC();
    int handler_cmd_SERVER_GAME_START_BC();
    int handler_cmd_SERVER_READY_BC();
    int handler_cmd_SERVER_GET_ONE_MJ();
    int handler_cmd_SERVER_OUT_ONE_MJ();
    int handler_cmd_SERVER_OPERATE_CHECK_AFTER_GETIN_MJ();
    int handler_cmd_SERVER_OPERATE_CHECK_OTHERS_PUTOUT_MJ();
    int handler_cmd_SERVER_OPERATE_CHECK_AFTER_PENG();
    int handler_cmd_SERVER_OPERATE_CHECK_QIANG_GANG_HU();
    int handler_cmd_SERVER_PASS();
    int handler_cmd_SERVER_PENG();
    int handler_cmd_SERVER_ANGGANG();
    int handler_cmd_SERVER_MINGGANG();
    int handler_cmd_SERVER_FANG_GANG();
    int handler_cmd_SERVER_ZIMOHU();
    int handler_cmd_SERVER_FANG_PAO_HU();
    int handler_cmd_SERVER_QIANG_GANG_HU(); 
    int handler_cmd_SERVER_GAME_READY_STAGE_BC(); 
    int handler_cmd_SERVER_GAME_END_BC(); 
    int handler_cmd_SERVER_REBIND_UC();
    int handler_cmd_SERVER_ERROR_UC();
    int handler_cmd_SERVER_DINGQUE_STARGE_BC();
    int handler_cmd_SERVER_DINGQUE_SUCC_BC();
    int handler_cmd_SERVER_CHONG_FENG_JI_BC();
    int handler_cmd_SERVER_BAO_TING_SUCC_BC();
    int handler_cmd_SERVER_ZHE_REN_JI_BC();
    int handler_cmd_SERVER_LOGIN_OTHER_DEVICE();
    int handler_cmd_SERVER_GOLDROOM_LOGOUT_ROOM();
    int handler_cmd_SERVER_BEGIN_ROBOT_OP_BC();
    int handler_cmd_SERVER_CANCEL_ROBOT_OP_SUCC_BC();
    

	string encode_json(const Json::Value& json_)
	{
		Json::FastWriter writer;
		return writer.write(json_);
	}

	Json::Value decode_json(const string& str)
	{
		Json::Value val;
		Json::Reader reader;
		if (!reader.parse(str, val))
		{
			throw std::exception();
		}
		return val;
	}
	int calculate_min_que(const vector<Mj>& hand_mjs) 
	{
		int c1 = 0, c2 = 0, c3 = 0;
		int dq = 1;
		for (auto mj : hand_mjs)
		{
			if (mj.color() == 1) c1++;
			else if (mj.color() == 2) c2++;
			else if (mj.color() == 3) c3++;
		}
		dq = (c2 < c3) ? 3 : 5;
		dq = (c1 < c2) ? 1 : dq;
		return dq;
	}
	Mj choose_outmj();
	int Expire() {
		int rand = random(0, 99);
		for (auto& info : _rule._out_time)
		{
			if (rand < info.second)
			{
				return info.first;
			}
			rand -= info.second;
		}
		return 0;
	}
	int PengExpire() {
		int rand = random(0, 99);
		for (auto& info : _rule._peng_time)
		{
			if (rand < info.second)
			{
				return info.first;
			}
			rand -= info.second;
		}
		return 0;
	}
	int GangExpire() {
		int rand = random(0, 99);
		for (auto& info : _rule._gang_time)
		{
			if (rand < info.second)
			{
				return info.first;
			}
			rand -= info.second;
		}
		return 0;
	}
	int HuExpire() {
		int rand = random(0, 99);
		for (auto& info : _rule._hu_time)
		{
			if (rand < info.second)
			{
				return info.first;
			}
			rand -= info.second;
		}
		return 0;
	}
public:
	int rest_mjs;	//剩余麻将数量
	int phone_num;
    int uid;
	int seatid;
    int money;
    int nbet;
	int count;

	int will_angang_mj;
	RobotRule	_rule;
	int _has_que;//	有无定缺
	vector<Mj> _hand_mjs;

	//GameTimer2 _join_room_timer;

    
	std::vector<int> last_cards;
	std::vector<int> out_cards;
    std::map<int,Players> players;
    int last_mo_mj;
	Json::Value read_root;

	boost::atomic<int> proto_cnt;
	boost::atomic<int> board_cnt;

	boost::atomic<bool> _on_seat;

	//GameTimer2 timer;
};


#endif
